package AutoNaturalDoc;

$OPEN_COMMENT  = "/*";
$CLOSE_COMMENT = "*/";
$PRIVATE_DOC   = "[Private]";
$PUBLIC_DOC    = "[Public]";
$STATIC_DOC    = "[Static]";
$linebreak = "\n";
$constructor = "";

###############################################################
# sub: checkClass
###############################################################
sub checkClass { #( $self, $inLine, $braceCount, $currentBrace, $inAuthor )
	my ( $self, $inLine, $braceCount, $currentBrace, $inAuthor ) = @_;
	# CHECK FOR CLASS...
	if (    $inLine =~ m/class/
		 && $inLine !~ m!//.*class!
		 && ( $braceCount - $currentBrace ) < 1 )
	{
		$main::isClass = 1;
		$superClass = "";
		$interfaceDoc = "";
		
		# Grab indent
		$inLine =~ m/^([\s]*)[^\s]/s;
		$docIndent = $1;

		# strip open brace
		$inLine =~ s/{//;

		# strip dynamic identifier (if present...)
		$isDynamic = $inLine =~ m/(dynamic).*class /;

		# strip intrinsic identifier (if present...)
		$isIntrinsic = $inLine =~ m/(intrinsic).*class /;

		# Get the className
		# match [words or the "."] after "class "
		$inLine =~ m/class ([\w.]*)/;
		$className = $1;

		# Get the constructor name
		@constructorName = split( m/\./, $className );
		our $constructor     = $constructorName[$#constructorName];
		
		# Strip whitespace
		$inLine =~ s/\s//g;
		if ( $inLine =~ m/implements/ ) {

			# Interface(s) are implemented...
			$inLine =~ m/implements(.*)/;
			$interfaces = $1;
			$interfaces =~ s/extends.*//g;
			@interface = split ",", $interfaces;
			for $iface (@interface) {
				$interfaceDoc .= "<" . $iface . ">" . $linebreak;
			}
		}
		if ( $inLine =~ m/extends/ ) {

			# This is a subClass
			$inLine =~ m/extends(.*)/;
			$superClass = $1;
			$superClass =~ s/implements.*//g;
		}

		# Create the doc...
		$lineDoc = $docIndent . $OPEN_COMMENT . $linebreak;
		$lineDoc .= $docIndent . "Class: $className" . $linebreak . $linebreak;
		$lineDoc .= $docIndent . "Description:" . $linebreak;

		# Place a description call to action here...
		$lineDoc .= $docIndent . "todo" . $linebreak . $linebreak;

		# If the class is intrinsic place a note at
		# the beginning of the description...
		if ( $isIntrinsic || $isDynamic ) {
			$lineDoc .= $docIndent . "Class Type:" . $linebreak . $docIndent;
			if ($isIntrinsic) {
				$lineDoc .= "[intrinsic]";
			}
			if ($isDynamic) {
				$lineDoc .= "[dynamic]";
			}
			$lineDoc .= $linebreak . $linebreak;
		}

   # If the class implements an interface place the doc heading and the interface(s) here.
		if ( $interfaceDoc ne "" ) {
			$lineDoc .= $docIndent . "Implements Interface(s):" . $linebreak;
			$lineDoc .= $interfaceDoc . $linebreak;
		}

   # If the class extends a class place the doc heading and the superclass here.
		if ( $superClass ne "" ) {
			$lineDoc .= $docIndent . "Extends Superclass:" . $linebreak;
			$lineDoc .= $docIndent . $superClass . $linebreak . $linebreak;
		}
		$lineDoc .=
		    $docIndent . "Usage:"
		  . $linebreak . ":todo"
		  . $linebreak
		  . $linebreak;
		$lineDoc .= $docIndent
		  . "Example:"
		  . $linebreak . ":todo"
		  . $linebreak
		  . $linebreak;
		$lineDoc .=
		  $docIndent . "ToDo:" . $linebreak . "..." . $linebreak . $linebreak;
		$lineDoc .=
		  $docIndent . "Notes:" . $linebreak . "todo" . $linebreak . $linebreak;
		$lineDoc .= $docIndent
		  . "Version:"
		  . $linebreak . "todo"
		  . $linebreak
		  . $linebreak;
		$lineDoc .= $docIndent
		  . "Author:"
		  . $linebreak . $inAuthor
		  . $linebreak
		  . $linebreak;

		# End the class comment.
		$lineDoc .= $docIndent . $CLOSE_COMMENT . $linebreak;
		return $lineDoc;
	}
}
###############################################################
# sub: checkClassProperty
###############################################################
sub checkClassProperty { #( $self, $inLine, $braceCount, $currentBrace )
	my ( $self, $inLine, $braceCount, $currentBrace ) = @_;
	#CHECK FOR CLASS PROPERTIES...
	if (    $inLine =~ m/var/
		 && $inLine !~ m!//.*var!
		 && ( $braceCount - $currentBrace ) < 2
		 && $main::isClass == 1 )
	{
		# Calculate indent
		$inLine =~ m/^([\s]*)[^\s]/s;
		$docIndent = $1;

		# remove ;
		$inLine =~ s/;//;

		# check member attributes
		$isPrivate = $inLine =~ m/private.*var/g;
		$isPublic  = $inLine =~ m/public.*var/g;
		$isStatic  = $inLine =~ m/static.*var/g;
		$inLine =~ m/^.*var(.*)/;
		$varString = $1;

		# strip whitepace
		$varString =~ s/\s//g;

		# grab the varName
		@varName = split( m/:/, $varString );
		( $varName, $dataType ) = @varName;
		$varName =~ s/=.*//g;
		if ( $dataType eq "" ) {
			$dataType = "Untyped";
		}
		$lineDoc = $docIndent . $OPEN_COMMENT . $linebreak;
		$lineDoc .=
		  $docIndent . "Property: " . $varName . $linebreak . $linebreak;
		$lineDoc .= $docIndent . "Description:" . $linebreak;

		# Place a description call to action here...
		$lineDoc .= $docIndent . "todo" . $linebreak . $linebreak;
		$lineDoc .= $docIndent
		  . "Datatype: "
		  . $linebreak
		  . $docIndent
		  . $dataType
		  . $linebreak
		  . $linebreak;
		$memberAttributes = "";
		if ($isPrivate) {
			$memberAttributes .= "[Private] ";
		}
		if ($isPublic) {
			$memberAttributes .= "[Public] ";
		}
		if ($isStatic) {
			$memberAttributes .= "[Static] ";
		}
		if ( $memberAttributes ne "" ) {
			$lineDoc .= $docIndent
			  . "Property type: "
			  . $linebreak
			  . $docIndent
			  . $memberAttributes
			  . $linebreak
			  . $linebreak;
		}
		$lineDoc .= $docIndent . $CLOSE_COMMENT . $linebreak;
		return $lineDoc;
	}
}
###############################################################
# sub: checkClassMethod
###############################################################
sub checkClassMethod { #( $self, $inLine, $braceCount, $currentBrace )
	my ( $self, $inLine, $braceCount, $currentBrace ) = @_;
	if (    $inLine =~ m/function/
		 && $inLine !~ m!//.*function!
		 && ( $braceCount - $currentBrace ) < 2
		 && $main::isClass == 1 )
	{
		# Calculate indent
		$inLine =~ m/^([\s]*)[^\s]/s;
		$docIndent = $1;

		#check for identifiers
		$isPrivate = $inLine =~ m/private.*function.*\(/g;
		$isPublic  = $inLine =~ m/public.*function.*\(/g;
		$isStatic  = $inLine =~ m/static.*function.*\(/g;
		$inLine =~ s/{//g;

		# strip whitespace
		$inLine =~ s/\s//g;

		# extract Method Name
		$inLine =~ m/^.*function(.*)\(/;
		$methodName = $1;

		# extract parameters string
		$inLine =~ m/^.*\((.*)\)/;
		$parameters = $1;

		# create parameters documentation stub
		$parametersList = "";
		@params = split ",", $parameters;
		for $param (@params) {    # any LIST expression
			@farg = split ":", $param;
			if ( $farg[1] eq "" ) {
				$farg[1] = "Untyped";
			}
			$parametersList .=
			  $docIndent . $farg[0] . " - [" . $farg[1] . "] todo" . $linebreak;
		}

		# extract return type
		$matchReturnType = $inLine =~ m/\):(.*)/;
		if ($matchReturnType) {
			$returnType = $1;
		}
		$lineDoc = $docIndent . $OPEN_COMMENT . $linebreak;
		$lineDoc .=
		  $docIndent . "Function: $methodName" . $linebreak . $linebreak;
		$lineDoc .= $docIndent . "Description:" . $linebreak;
		if ( our $constructor eq $methodName ) {
			$constructorNote = "Constructor ";
		} else {
			$constructorNote = "";
		}

		# Place a description call to action here...
		$lineDoc .=
		  $docIndent . $constructorNote . "todo" . $linebreak . $linebreak;
		$memberAttributes = "";
		if ($isPrivate) {
			$memberAttributes .= $PRIVATE_DOC;
		}
		if ($isPublic) {
			$memberAttributes .= $PUBLIC_DOC;
		}
		if ($isStatic) {
			$memberAttributes .= $STATIC_DOC;
		}
		if ( $memberAttributes ne "" ) {
			$lineDoc .= $docIndent
			  . "Method type: "
			  . $linebreak
			  . $docIndent
			  . $memberAttributes
			  . $linebreak
			  . $linebreak;
		}
		if ( $parametersList ne "" ) {
			$lineDoc .= $docIndent
			  . "Parameters: "
			  . $linebreak
			  . $parametersList
			  . $linebreak;
		}
		if ($matchReturnType) {
			$lineDoc .= $docIndent
			  . "Return: "
			  . $linebreak
			  . $docIndent
			  . $returnType
			  . $linebreak
			  . $docIndent . "todo"
			  . $linebreak
			  . $linebreak;
		}
		$lineDoc .= $docIndent . $CLOSE_COMMENT . $linebreak;
		return $lineDoc;
	}
}
###############################################################
# sub: checkInterface
###############################################################
sub checkInterface { #( $self, $inLine, $braceCount, $currentBrace, $inAuthor )
	my ( $self, $inLine, $braceCount, $currentBrace, $inAuthor ) = @_;
	if (    $inLine =~ m/interface/
		 && $inLine !~ m!//.*interface!
		 && ( $braceCount - $currentBrace ) < 1 )
	{
		# print "found interface\n";
		$main::isClass = 0;

		# Calculate indent
		$inLine =~ m/^([\s]*)[^\s]/s;
		$docIndent = $1;

		# strip open brace
		$inLine =~ s/{//;

		# Strip whitespace
		$inLine =~ s/\s//g;

		# see if the interface definition is a subclass
		$isSubInterface = $inLine =~ s/extends(.*)//;
		$superInterface = $1;
		@interface      = split ",", $superInterface;
		$interfaceDoc   = "";
		for $iface (@interface) {
			$interfaceDoc .= "<" . $iface . ">" . $linebreak;
		}

		# Get the interface name
		$interfaceName   = $inLine;

		$lineDoc         = $docIndent . $OPEN_COMMENT . $linebreak;
		$lineDoc .= $docIndent . "Interface: $interfaceName" . $linebreak . $linebreak;
		$lineDoc .= $docIndent . "Description:" . $linebreak;

		# Place a description call to action here...
		$lineDoc .= $docIndent . "todo" . $linebreak . $linebreak;

		# If this is a subInterface then show which interface is extended.
		if ($isSubInterface) {
			$lineDoc .= $docIndent
			  . "Extends Interface:"
			  . $linebreak
			  . $interfaceDoc
			  . $linebreak;
		}
		$lineDoc .=
		  $docIndent . "ToDo:" . $linebreak . "" . $linebreak . $linebreak;
		$lineDoc .=
		  $docIndent . "Notes:" . $linebreak . "todo" . $linebreak . $linebreak;
		$lineDoc .= $docIndent
		  . "Version:"
		  . $linebreak . "todo"
		  . $linebreak
		  . $linebreak;
		$lineDoc .= $docIndent
		  . "Author:"
		  . $linebreak . $inAuthor
		  . $linebreak
		  . $linebreak;

		# End the interface comment.
		$lineDoc .= $docIndent . $CLOSE_COMMENT . $linebreak;
		return $lineDoc;
	}
}
###############################################################
# sub: checkInterfaceMethod
###############################################################
sub checkInterfaceMethod { #( $self, $inLine, $braceCount, $currentBrace )
	my ( $self, $inLine, $braceCount, $currentBrace ) = @_;
	if (    $inLine =~ m/function/
		 && $inLine !~ m!//.*function!
		 && ( $braceCount - $currentBrace ) < 2
		 && $main::isClass == 0 )
	{
		# Calculate indent
		$inLine =~ m/^([\s]*)[^\s]/s;
		$docIndent = $1;
		$parametersList = "";

		#Strip whitespace
		$inLine =~ s/\s//g;

		# extract Method Name
		if ($inLine =~ m/^.*function(.*)\(/ ) {
			$methodName = $1;
		} else {
			$methodName = "";
		}
		
		# extract parameters string
		$inLine =~ m/^.*\((.*)\)/;
		$parameters = $1;

		# create parameters documentation stub
		$parametersList = "";
		@params = split ",", $parameters;
		for $param (@params) {    # any LIST expression
			@farg = split ":", $param;
			if ($farg[0] && $farg[1]) {
				$parametersList .= $docIndent . $farg[0] . " - [" . $farg[1] . "] todo" . $linebreak;
			}
		}

		# extract return type
		$matchReturnType = $inLine =~ m/\):(.*)/;
		if ($matchReturnType) {
			$returnType = $1;
		}
		$lineDoc = $docIndent . $OPEN_COMMENT . $linebreak;
		$lineDoc .= $docIndent . "Function: $methodName" . $linebreak . $linebreak;
		$lineDoc .= $docIndent . "Description:" . $linebreak;
		# Place a description call to action here...
		$lineDoc .= $docIndent . "todo" . $linebreak . $linebreak;

		if ( $parametersList ne "" ) {
			$lineDoc .= $docIndent
			  . "Parameters: "
			  . $linebreak
			  . $parametersList
			  . $linebreak;
		}
		if ($matchReturnType) {
			$lineDoc .= $docIndent
			  . "Return: "
			  . $linebreak
			  . $docIndent
			  . $returnType
			  . $linebreak
			  . $docIndent . "todo"
			  . $linebreak
			  . $linebreak;
		}
		$lineDoc .= $docIndent . $CLOSE_COMMENT . $linebreak;
		return $lineDoc;
	}
}
1;